"""
定时任务调度器
定时获取股票数据、计算买卖点并保存到数据库
在交易时间段内每5分钟更新一次
"""
import logging
import time
import threading
from datetime import datetime
from typing import List

from api.stock_api import StockAPIClient
from analysis.signal_generator import SignalGenerator
from database import SessionLocal, StockPrice as DBStockPrice, TradingSignal as DBTradingSignal
from config import config

logger = logging.getLogger(__name__)

class StockDataScheduler:
    """股票数据定时调度器"""
    
    def __init__(self):
        self.stock_api = StockAPIClient()
        self.signal_generator = SignalGenerator()
        self.is_running = False
        self.thread = None
    
    def fetch_and_save_stock_data(self, symbol: str):
        """获取并保存单个股票的数据"""
        try:
            logger.info(f"📊 开始获取股票数据: {symbol}")
            
            # 获取历史数据（最近1天）
            history = self.stock_api.get_history_data(symbol, days=1)
            
            if not history:
                logger.warning(f"⚠️ {symbol} 无数据")
                return
            
            # 获取数据库会话
            db = SessionLocal()
            
            try:
                # 保存价格数据
                for price_data in history:
                    # 检查是否已存在
                    existing = db.query(DBStockPrice).filter(
                        DBStockPrice.symbol == symbol,
                        DBStockPrice.timestamp == price_data['timestamp']
                    ).first()
                    
                    if not existing:
                        db_price = DBStockPrice(
                            symbol=symbol,
                            timestamp=price_data['timestamp'],
                            open=price_data['open'],
                            high=price_data['high'],
                            low=price_data['low'],
                            close=price_data['close'],
                            volume=price_data['volume']
                        )
                        db.add(db_price)
                
                db.commit()
                logger.info(f"✅ {symbol} 数据已保存")
                
            finally:
                db.close()
                
        except Exception as e:
            logger.error(f"❌ 获取 {symbol} 数据失败: {e}")
    
    def calculate_and_save_signals(self, symbol: str):
        """计算并保存交易信号"""
        try:
            logger.info(f"🎯 开始计算交易信号: {symbol}")
            
            # 获取历史数据用于计算
            history = self.stock_api.get_history_data(symbol, days=90)
            
            if not history or len(history) < 30:
                logger.warning(f"⚠️ {symbol} 数据不足，无法计算信号")
                return
            
            # 生成交易信号
            signal = self.signal_generator.generate_signal(symbol, history)
            
            if not signal:
                logger.warning(f"⚠️ {symbol} 无法生成信号")
                return
            
            # 保存到数据库
            db = SessionLocal()
            
            try:
                # 检查今天是否已有信号
                today = datetime.now().date()
                existing = db.query(DBTradingSignal).filter(
                    DBTradingSignal.symbol == symbol,
                    DBTradingSignal.signal_date == today
                ).first()
                
                if existing:
                    # 更新现有信号
                    existing.signal_type = signal['signal_type']
                    existing.price = signal['price']
                    existing.strength = signal['strength']
                    existing.reason = signal['reason']
                    existing.action_price = signal.get('action_price')  # 修复：保存建议买入价
                    existing.target_price = signal.get('target_price')
                    existing.stop_loss = signal.get('stop_loss')
                    # 保存技术指标数据
                    import json
                    existing.indicators = json.dumps(signal.get('indicators', {})) if signal.get('indicators') else None
                    logger.info(f"🔄 {symbol} 信号已更新")
                else:
                    # 创建新信号
                    import json
                    db_signal = DBTradingSignal(
                        symbol=symbol,
                        signal_type=signal['signal_type'],
                        price=signal['price'],
                        strength=signal['strength'],
                        reason=signal['reason'],
                        action_price=signal.get('action_price'),  # 修复：保存建议买入价
                        target_price=signal.get('target_price'),
                        stop_loss=signal.get('stop_loss'),
                        # 保存技术指标数据
                        indicators=json.dumps(signal.get('indicators', {})) if signal.get('indicators') else None,
                        signal_date=today
                    )
                    db.add(db_signal)
                    logger.info(f"✅ {symbol} 新信号已保存")
                
                db.commit()
                
            finally:
                db.close()
                
        except Exception as e:
            logger.error(f"❌ 计算 {symbol} 信号失败: {e}")
    
    def process_all_stocks(self):
        """处理所有股票（优化版本：支持200只股票）"""
        start_time = datetime.now()
        logger.info("="*70)
        logger.info(f"⏰ 定时任务开始: {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
        logger.info(f"📊 处理股票数量: {len(config.POPULAR_STOCKS)}只")
        logger.info("="*70)
        
        processed_count = 0
        error_count = 0
        
        for i, symbol in enumerate(config.POPULAR_STOCKS, 1):
            try:
                # 显示进度
                if i % 20 == 0 or i == len(config.POPULAR_STOCKS):
                    progress = (i / len(config.POPULAR_STOCKS)) * 100
                    logger.info(f"📈 处理进度: {i}/{len(config.POPULAR_STOCKS)} ({progress:.1f}%)")
                
                # 获取并保存数据
                full_symbol = f"sh{symbol}" if symbol.startswith("6") else f"sz{symbol}"
                self.fetch_and_save_stock_data(full_symbol)
                
                # 计算并保存信号
                self.calculate_and_save_signals(full_symbol)
                
                processed_count += 1
                
                # 进一步减少延迟时间，提高处理效率（改为0.5秒）
                time.sleep(0.5)
                
            except Exception as e:
                error_count += 1
                logger.error(f"❌ 处理股票 {symbol} 失败: {e}")
                continue
        
        end_time = datetime.now()
        duration = (end_time - start_time).total_seconds()
        
        logger.info("="*70)
        logger.info(f"✅ 定时任务完成: {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
        logger.info(f"📊 处理统计: 成功 {processed_count}只, 失败 {error_count}只")
        logger.info(f"⏱️ 耗时: {duration:.1f}秒 ({duration/60:.1f}分钟)")
        logger.info(f"⚡ 平均处理速度: {duration/len(config.POPULAR_STOCKS):.1f}秒/股")
        logger.info("="*70)
    
    def is_trading_time(self):
        """判断当前是否是交易时间"""
        now = datetime.now()
        current_time = now.time()
        current_weekday = now.weekday()
        
        # 周末不交易（周六=5, 周日=6）
        if current_weekday >= 5:
            return False
        
        # 交易时间段：
        # 上午：9:30-11:30
        # 下午：13:00-15:00
        from datetime import time as dt_time
        
        morning_start = dt_time(9, 30)
        morning_end = dt_time(11, 30)
        afternoon_start = dt_time(13, 0)
        afternoon_end = dt_time(15, 0)
        
        is_morning = morning_start <= current_time <= morning_end
        is_afternoon = afternoon_start <= current_time <= afternoon_end
        
        return is_morning or is_afternoon
    
    def start(self):
        """启动定时任务"""
        if self.is_running:
            logger.warning("⚠️ 定时任务已在运行")
            return
        
        self.is_running = True
        
        logger.info("🚀 启动定时任务调度器")
        logger.info("⏰ 定时计划: 交易时间段每1小时更新一次")
        logger.info("  📈 上午交易时间: 09:30 - 11:30")
        logger.info("  📈 下午交易时间: 13:00 - 15:00")
        logger.info("  🔄 更新频率: 每1小时")
        logger.info("📊 监控股票: " + ", ".join(config.POPULAR_STOCKS))
        
        # 首次启动立即执行一次
        self.process_all_stocks()
        
        # 在后台线程中运行调度器
        def run_scheduler():
            last_run_time = datetime.now()
            
            while self.is_running:
                now = datetime.now()
                
                # 检查是否是交易时间
                if self.is_trading_time():
                    # 计算距离上次运行的时间差
                    time_diff = (now - last_run_time).total_seconds()
                    
                    # 如果距离上次运行超过1小时（3600秒），则执行任务
                    if time_diff >= 3600:
                        logger.info(f"⏰ 触发定时任务（距上次运行 {int(time_diff/60)} 分钟）")
                        self.process_all_stocks()
                        last_run_time = now
                    else:
                        # 等待到下一个1小时间隔
                        remaining = 3600 - time_diff
                        logger.debug(f"⏳ 交易时间内，下次更新还需 {int(remaining/60)} 分钟")
                else:
                    # 非交易时间，等待到下一个交易时段
                    logger.debug(f"💤 非交易时间，等待中... (当前时间: {now.strftime('%H:%M:%S')})")
                
                # 每分钟检查一次
                time.sleep(60)
        
        self.thread = threading.Thread(target=run_scheduler, daemon=True)
        self.thread.start()
        
        logger.info("✅ 定时任务调度器已启动（交易时间每5分钟更新）")
    
    def stop(self):
        """停止定时任务"""
        self.is_running = False
        if self.thread and self.thread.is_alive():
            self.thread.join(timeout=5)
        logger.info("⏹️ 定时任务调度器已停止")

# 全局调度器实例
scheduler = StockDataScheduler()

